package predatorpreysystems;
/*
 * Copyright (c) 2009 Project E7
 *
 * This file is part of PredatorPreySystems
 *
 * PredatorPreySystems is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PredatorPreySystems is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PredatorPreySystems. If not, see <http://www.gnu.org/licenses/>.
 *
 * PredatorPreySystems is a project that demonstrates lotka volterra's predator
 * prey systems.  The project is also meant to demonstrate linear approximation
 * using differential equations and Euler's method.
 **/

import info.gridworld.actor.Actor;
import info.gridworld.actor.Critter;
import info.gridworld.grid.Location;
import java.awt.Color;
import java.util.ArrayList;

/**
 *
 * @author markvismonte
 */
public class Predator extends Critter
    {
    private static final double DARKENING_FACTOR = 0.25;
    //Data Members
    private int turnsTilDeath;
    private int eatenPrey;
    private int babyPerPrey;
    private int turnsWithoutFood;
    private PredatorPreySystemUtility pps;

    /**
     * Makes a new predator which extends Critter
     * @param turnsTilDeath - Turns until death without food
     * @param babyPerPrey - amount of eaten prey for every offspring
     */
    public Predator(int turnsTilDeath, int babyPerPrey)
        {
        super();
        setColor(Color.GREEN);
        this.turnsTilDeath = turnsTilDeath;
        eatenPrey = turnsWithoutFood = 0;
        this.babyPerPrey = babyPerPrey;
        pps = Main.getPpsUtility();
        }

    /**
     * Interface for to the method predictFuturePopulation in pps in order to
     * predict future predator population
     * @param turns - how many turns in the future to predict to
     * @param stepSize - how far t is travelled in a step
     * @return - an approximation of the future predator population
     */
    public int predictFuturePredatorPopulation(int turns, double stepSize)
        {
        return pps.predictFuturePopulation(false, true, pps.getPreyPopulation(),
                pps.getPredatorPopulation(), 0.0, 0.0, 0.0, 0.0, stepSize, 0.0,
                turns);
        }

    private void depriciateColor()
        {
        Color c = getColor();
        int red = (int) (c.getRed() * (1 - DARKENING_FACTOR));
        int green = (int) (c.getGreen() * (1 - DARKENING_FACTOR));
        int blue = (int) (c.getBlue() * (1 - DARKENING_FACTOR));

        setColor(new Color(red, green, blue));
        }

    @Override
    /**
     * Eats all the actors within in any square and any direction
     */
    public void processActors(ArrayList<Actor> actors)
        {
        turnsWithoutFood++;
        for (Actor a: actors)
            if (a instanceof Prey)
                {
                a.removeSelfFromGrid();
                eatenPrey++;
                turnsWithoutFood = 0;
                }
        }

    @Override
    /**
     * Calls super.act()
     * Dies when it hasn't eaten
     * Makes offspring when enough prey has been eaten
     */
    public void act()
        {
        Location loc = getLocation();
        super.act();
        if (turnsWithoutFood >= turnsTilDeath)
            {
            removeSelfFromGrid();
            setColor(Color.GREEN);
            }
        else
            depriciateColor();
        if (eatenPrey >= babyPerPrey)
            {
            (new Predator(turnsTilDeath, babyPerPrey)).putSelfInGrid(getGrid(),
                    loc);
            eatenPrey -= babyPerPrey;
            pps.incrementPredatorGrowth();
            }
        }

    @Override
    /**
     * Calls super.removeSelfFromGrid() and increments predator decay in pps
     */
    public void removeSelfFromGrid() {
        super.removeSelfFromGrid();
        pps.incrementPredatorDecay();
        }

    @Override
    /**
     * Returns a location towards food
     */
    public ArrayList<Location> getMoveLocations() {
        Location toFood = pps.locationTowardsFood(getLocation());
        ArrayList<Location> ret = getGrid().getValidAdjacentLocations(
                getLocation().getAdjacentLocation(getLocation().
                getDirectionToward(toFood)));
        ret.remove(getLocation());
        return ret;
        }

    }
